package pl.org.lutra.planner.log;

import java.util.logging.FileHandler;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.LogManager;
import java.util.logging.LogRecord;

public class DefaultLogger implements Logger {
    private final java.util.logging.Logger logger = java.util.logging.Logger.getLogger("plannerLogger");
    
    DefaultLogger(boolean debug) {
        LogManager.getLogManager().reset();
        
        LogFormatter formatter = new LogFormatter();
        
        SysOutConsoleHandler consoleHandler = new SysOutConsoleHandler();
        consoleHandler.setFormatter(formatter);
        
        logger.addHandler(consoleHandler);
        
        try {
            FileHandler fileHandler =
                    FileHandlerFactory.createFileHandler("logs" + System.getProperty("file.separator")
                            + "planner.log");
            fileHandler.setFormatter(formatter);
            
            logger.addHandler(fileHandler);
        } catch (Exception exception) {
            error("Cannot initialize logging to file", exception);
        }
        
        if (debug) {
            logger.setLevel(Level.FINE);
            
            for (Handler handler : logger.getHandlers()) {
                handler.setLevel(Level.FINE);
            }
        }
    }
    
    @Override
    public void error(String message, Throwable exception) {
        LogRecord record = createRecord(Level.SEVERE, message, exception);
        logger.log(record);
    }
    
    @Override
    public void warning(String message, Throwable exception) {
        LogRecord record = createRecord(Level.WARNING, message, exception);
        logger.log(record);
    }
    
    @Override
    public void info(String message, Throwable exception) {
        LogRecord record = createRecord(Level.INFO, message, exception);
        logger.log(record);
    }
    
    @Override
    public void debug(String message, Throwable exception) {
        LogRecord record = createRecord(Level.FINE, message, exception);
        logger.log(record);
    }
    
    private static LogRecord createRecord(Level level, String message, Throwable exception) {
        LogRecord record = new LogRecord(level, message);
        record.setThrown(exception);
        
        Object[] parameters = new Object[2];
        record.setParameters(parameters);
        
        StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
        boolean thisLine = false;
        for (StackTraceElement ste : stackTrace) {
            if (Log.class.getName().equals(ste.getClassName())) {
                thisLine = true;
                continue;
            }
            if (thisLine) {
                record.setSourceClassName(ste.getClassName());
                record.setSourceMethodName(ste.getMethodName());
                
                parameters[0] = ste.getFileName();
                parameters[1] = ste.getLineNumber();
                
                break;
            }
        }
        return record;
    }
}
